/* test_io_pipes_1():
	A basic test for uthread_pipe(), uthread_read(), uthread_write().

	This test does:

	* Create additional thread: 1.
	* Thread 0 creates the pipe 'P'.
	* Thread 0 reads a byte from P.
	* Thread 1 does some long operation, and then write a byte to P.
*/


#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>


#include "test_general.h"
#include "user_threads.h"
#include "user_io.h"


bool test_io_pipes_1();


#define THREADS_NUM 2


int P_fd[2];

static int thread1_start_routine(void * param) {
	TEST_ASSERT (uthread_self() == 1);

	some_long_operation(0.5);

	TEST_ASSERT(last_running_times[0] < last_running_times[1]-0.4);
		// Verifying that threwad 0 was blocked all this time.

	int x = 1507;
	int tmp = uthread_write(P_fd[1],&x,sizeof(x));
	TEST_ASSERT(sizeof(x) == tmp);
	// Now thread 0 returns to run.

	some_long_operation(0.1);
	TEST_ASSERT(last_running_times[0] > last_running_times[1]-0.1);

	thread_ok[1] = true;
	return 0;
}


bool test_io_pipes_1()
{
	init_individual_test();

	int tmp;

	if (initilize_uthread_in_each_test) {
		tmp = uthread_init();
		TEST_ASSERT(tmp == UTHREAD_SUCCESS);
	}

	thread_id threads[THREADS_NUM];

	threads[0] = uthread_self();
	TEST_ASSERT(threads[0] == 0);

	int FiftyThree = 53;

	threads[1] = uthread_create(thread1_start_routine, &FiftyThree);
	TEST_ASSERT(threads[1] == 1);

	some_long_operation(0.01);

	tmp = uthread_pipe(P_fd);
	TEST_ASSERT(tmp == 0);

	int x;
	tmp = uthread_read(P_fd[0],&x,sizeof(x));
	TEST_ASSERT(sizeof(x) == tmp);
	TEST_ASSERT(1507 == x);

	TEST_ASSERT(last_running_times[0] < last_running_times[1]-0.4);

	close (P_fd[0]);
	close (P_fd[1]);

	some_long_operation(0.01);

	tmp = uthread_join(1,NULL);
	TEST_ASSERT(tmp == UTHREAD_SUCCESS);

	thread_ok[0] = true;
	TEST_ASSERT(are_all_threads_ok(THREADS_NUM));

	return true;
}

